package gagak.framework.web.core;

import com.g5.framework.web.context.request.RequestAttributes;
import com.g5.framework.web.context.request.RequestContextHolder;
import com.g5.framework.web.context.request.ServletRequestAttributes;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/*
 * @program: ce
 * @description: 对接servelet 完成请求集中处理
 * @author: houhong
 * @create: 2022-12-01 16:57
 */
public abstract class FrameworkServlet extends GenernicServlet {

    private Logger logger = LoggerFactory.getLogger(getClass());


    /*
     * 启动上下文threaderLocal
     */
    private boolean threadContextInheritable = true;

    /*
     * TODO: 2022/11/23  主要做一些对接servlet规范的东西
     */
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        processRequest(req, resp);
    }

    @Override
    protected long getLastModified(HttpServletRequest req) {
        return super.getLastModified(req);
    }

    @Override
    protected void doHead(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        super.doHead(req, resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        processRequest(req, resp);
    }

    @Override
    protected void doPut(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        processRequest(req, resp);
    }

    @Override
    protected void doDelete(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        processRequest(req, resp);
    }

    @Override
    protected void doOptions(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        super.doOptions(req, resp);
    }

    @Override
    protected void doTrace(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        processRequest(req, resp);
    }

    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        processRequest(req, resp);
    }

    /*
     * 将所有的请求全部下发到这里来
     */
    protected final void processRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        // 存储request上下文 供其他地方使用
        RequestAttributes previousAttributes = RequestContextHolder.getRequestAttributes();
        //生成一个attributes
        ServletRequestAttributes requestAttributes = buildRequestAttributes(request, response, previousAttributes);
        //初始化属性，将request的Attributes 放进来
        initContextHolder(request, requestAttributes);

        // 干活
        try {
            doService(request, response);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            //删除ContextHolder
        }

    }


    private void initContextHolder(HttpServletRequest request, ServletRequestAttributes requestAttributes) {

        if (requestAttributes != null) {
            RequestContextHolder.setRequestAttributes(requestAttributes, this.threadContextInheritable);
        }
        if (logger.isTraceEnabled()) {
            logger.trace("Bound request context to thread: " + request);
        }
    }


    /*
     * 初始化上下文
     */
    private ServletRequestAttributes buildRequestAttributes(HttpServletRequest request, HttpServletResponse response,
                                                            RequestAttributes previousAttributes) {

        if (previousAttributes == null || previousAttributes instanceof ServletRequestAttributes) {
            return new ServletRequestAttributes(request, response);
        } else {
            return null;
        }
    }


    /*
     * 完成工作,交给Dispartch来完成
     */
    public abstract void doService(HttpServletRequest request, HttpServletResponse response);
}